package pers.wang.toolset.coder.util.encryption;

import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.Cipher;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.ArrayUtils;

public class RSACoderUtil {
	 //非对称密钥算法
    public static final String KEY_ALGORITHM = "RSA";


    /**
     * 密钥长度，DH算法的默认密钥长度是1024
     * 密钥长度必须是64的倍数，在512到65536位之间
     */
    private static final int KEY_SIZE = 1024;
    //公钥
    private static final String PUBLIC_KEY = "RSAPublicKey";

    //私钥
    private static final String PRIVATE_KEY = "RSAPrivateKey";

    /**
     * 初始化密钥对
     *
     * @return Map 甲方密钥的Map
     */
    public static Map<String, Object> initKey() throws Exception {
        //实例化密钥生成器
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
        //初始化密钥生成器
        keyPairGenerator.initialize(KEY_SIZE);
        //生成密钥对
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        //甲方公钥
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        //甲方私钥
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        //将密钥存储在map中
        Map<String, Object> keyMap = new HashMap<String, Object>();
        keyMap.put(PUBLIC_KEY, publicKey);
        keyMap.put(PRIVATE_KEY, privateKey);
        return keyMap;

    }


    /**
     * 私钥加密
     *
     * @param data 待加密数据
     * @param key       密钥
     * @return byte[] 加密数据
     */
    public static byte[] encryptByPrivateKey(byte[] data, byte[] key) throws Exception {
    	data = Base64.encodeBase64(data);
        //取得私钥
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(key);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        //生成私钥
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
        //数据加密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
        
        // 加密时超过117字节就报错。为此采用分段加密的办法来加密   
        byte[] enBytes = null;  
        for (int i = 0; i < data.length; i += 64) {    
        // 注意要使用2的倍数，否则会出现加密后的内容再解密时为乱码  
            byte[] doFinal = cipher.doFinal(ArrayUtils.subarray(data, i,i + 64));    
            enBytes = ArrayUtils.addAll(enBytes, doFinal);    
        }  
        return enBytes;
    }

    /**
     * 公钥加密
     *
     * @param data 待加密数据
     * @param key       密钥
     * @return byte[] 加密数据
     */
    public static byte[] encryptByPublicKey(byte[] data, byte[] key) throws Exception {

        //实例化密钥工厂
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        //初始化公钥
        //密钥材料转换
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(key);
        //产生公钥
        PublicKey pubKey = keyFactory.generatePublic(x509KeySpec);

        //数据加密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
     // 加密时超过117字节就报错。为此采用分段加密的办法来加密   
        byte[] enBytes = null;  
        for (int i = 0; i < data.length; i += 64) {    
        // 注意要使用2的倍数，否则会出现加密后的内容再解密时为乱码  
            byte[] doFinal = cipher.doFinal(ArrayUtils.subarray(data, i,i + 64));    
            enBytes = ArrayUtils.addAll(enBytes, doFinal);    
        }  
        return enBytes;
    }

    /**
     * 私钥解密
     *
     * @param data 待解密数据
     * @param key  密钥
     * @return byte[] 解密数据
     */
    public static byte[] decryptByPrivateKey(byte[] data, byte[] key) throws Exception {
        //取得私钥
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(key);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        //生成私钥
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
        //数据解密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
     // 解密时超过128字节就报错。为此采用分段解密的办法来解密  
        StringBuilder sb = new StringBuilder();  
        for (int i = 0; i < data.length; i += 128) {  
            byte[] doFinal = cipher.doFinal(ArrayUtils.subarray(data, i, i + 128));  
            sb.append(new String(doFinal));  
        }  
        return Base64.decodeBase64(sb.toString().getBytes());
    }

    /**
     * 公钥解密
     *
     * @param data 待解密数据
     * @param key  密钥
     * @return byte[] 解密数据
     */
    public static byte[] decryptByPublicKey(byte[] data, byte[] key) throws Exception {

        //实例化密钥工厂
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        //初始化公钥
        //密钥材料转换
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(key);
        //产生公钥
        PublicKey pubKey = keyFactory.generatePublic(x509KeySpec);
        //数据解密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, pubKey);
        // 解密时超过128字节就报错。为此采用分段解密的办法来解密  
        StringBuilder sb = new StringBuilder();  
        for (int i = 0; i < data.length; i += 128) {  
            byte[] doFinal = cipher.doFinal(ArrayUtils.subarray(data, i, i + 128));  
            sb.append(new String(doFinal));  
        }  
        return Base64.decodeBase64(sb.toString().getBytes());
    }

    /**
     * 取得私钥
     *
     * @param keyMap 密钥map
     * @return byte[] 私钥
     */
    public static byte[] getPrivateKey(Map<String, Object> keyMap) {
        Key key = (Key) keyMap.get(PRIVATE_KEY);
        return key.getEncoded();
    }

    /**
     * 取得公钥
     *
     * @param keyMap 密钥map
     * @return byte[] 公钥
     */
    public static byte[] getPublicKey(Map<String, Object> keyMap) throws Exception {
        Key key = (Key) keyMap.get(PUBLIC_KEY);
        return key.getEncoded();
    }

    /**
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
    	byte[] prk = Base64.decodeBase64("MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJATZMFswaTfPnNv2QpAPkRg4sVdXGZYCSWot8vGAnbIQeStNj3bPpUjHlLIKNHp0lk5sXti1Yez8At2otiNCe7/BG6YIhVQntzFa6L3QVJP71oluewnjWGQQq8nctOxt6JZNY4ed5q1V5OzsFRCIE44l8pw5BP0gD1kczQp10ejAgMBAAECgYAjWr70wA1cufOHPEEUROOCwAulxt0vuBa2iQphFLvyDf4tcVvIHg7jZfTA96EcsbYOcxvcXUpsvHkBNyGK5kEzZzlNmoRZ43TX5HXmIS2CObK1yLouJAQi3EAtTouumTf5FfHbtwHu+Gwtzk02qXPI/Anvq039rRvdWt6NwOXaAQJBAOA8e7ASBmFmnEFyZohEB0SXRWbfTranzLNzz0sHonUgoH4fUkdCCcFw1M4Gj0PbT+0Rjq1jsUR6dwRPk+4C2CMCQQCkfAli264nTfmgP32WH2ZfeVOyJtGOBenspXY3ArerV1QnxEqJFlWquNVVnfl7SSALfF5h5SpRoja3T1P2HQqBAkEAy5c+ufLzphWTA30KCOizLJyn36oafo7FtZ0NddL9tpij/z8S5i3YS7DVFiYwh2ylGdqaD2V3enQygVB7QFuGvwJAVs0iQuo9YH6Uwk1fIA8X/kBPu88ifTl/tiOnW+ZyONiQD6BV2TxRHxQFePYyBy6S25zZTf4atBPPnjMd0t6GgQJAKUStqie4oWroW+WEadJxZjcJC2uZhGt0hpXiGxmwfvcZHjUOSjOgfxHQTXBm4mEVJu+UuEGQrmhAVkTBSdCVYA==");
    	byte[] b = RSACoderUtil.encryptByPrivateKey("a水电费士大夫士大夫撒发士大夫撒飞洒士大夫撒发士大夫撒飞洒士大夫撒发士大夫撒飞洒士大夫撒发士大夫撒飞洒士大夫撒发士大夫撒飞洒士大夫撒发士大夫撒飞洒士大夫撒发士大夫撒飞洒士大夫撒发士大夫撒飞洒士大夫撒发士大夫撒飞洒士大夫撒发士大夫撒飞洒士大夫撒发士大夫撒飞洒士大夫撒发士大夫撒飞洒士大夫撒发士大夫撒飞洒士大夫撒发士大夫撒飞洒士大夫撒发士大夫撒飞洒士大夫撒发士大夫撒飞洒士大夫撒发士大夫撒飞洒士大夫撒发士大夫撒飞洒士大夫撒发士大夫撒飞洒士大夫撒发士大夫撒飞洒士大夫撒发士大夫撒飞士大夫撒发士大夫撒飞士大夫撒发士大夫撒飞士大夫撒发士大夫撒飞发撒飞洒发撒的发撒地方撒旦发阿士大夫撒发放的撒旦法bc".getBytes(),  prk);
    	byte[] puk =  Base64.decodeBase64("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCQE2TBbMGk3z5zb9kKQD5EYOLFXVxmWAklqLfLxgJ2yEHkrTY92z6VIx5SyCjR6dJZObF7YtWHs/ALdqLYjQnu/wRumCIVUJ7cxWui90FST+9aJbnsJ41hkEKvJ3LTsbeiWTWOHneatVeTs7BUQiBOOJfKcOQT9IA9ZHM0KddHowIDAQAB");
    	
    	byte[] bb = RSACoderUtil.decryptByPublicKey(b, puk);
    	System.out.println(new String(bb));
    }
}
